package com.artron.mediaartron.ui.adapter;

import android.os.Handler;
import android.os.Looper;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;

import com.artron.baselib.adapter.recyclerview.HeaderAndFooterWrapper;
import com.artron.baselib.adapter.recyclerview.LoadMoreWrapper;
import com.artron.baselib.adapter.recyclerview.MultiItemTypeAdapter;
import com.artron.baselib.entity.Response;
import com.artron.mediaartron.R;
import com.artron.mediaartron.data.entity.IsLoadMore;

import java.util.ArrayList;
import java.util.List;

import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action0;
import rx.functions.Action1;
import rx.functions.Func1;
import rx.schedulers.Schedulers;


/**
 * Class description here
 *
 * @author doing
 * @version 1.0.0
 * @since 2017-08-02.
 */

public class LoadMoreListener<T extends IsLoadMore<S>, S> implements LoadMoreWrapper.OnLoadMoreListener {

    private static final String TAG = "LoadMoreListener";

    private final Func1<Integer, Observable<Response<T>>> func;
    private final List<S> mData;

    private LoadMoreWrapper mRecyclerAdapter;
    private int mPage = 1;

    protected boolean isUpdateLastOne = false;


    public LoadMoreListener(List<S> data, LoadMoreWrapper adapter,
                            Func1<Integer, Observable<Response<T>>> func) {
        this.func = func;
        this.mData = data;
        this.mRecyclerAdapter = adapter;
    }

    public void setAdapter(LoadMoreWrapper adapter) {
        mRecyclerAdapter = adapter;
    }

    @Override
    public void onLoadMoreRequested(RecyclerView.ViewHolder holder) {
        loadMoreData(holder);
    }

    private void loadMoreData(final RecyclerView.ViewHolder holder) {
        mPage++;
        func.call(mPage)
                .map(new Func1<Response<T>, T>() {
                    @Override
                    public T call(Response<T> tResponse) {
                        return tResponse.getData();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<T>() {
                    @Override
                    public void call(T data) {
                            Log.d(TAG, "call: " + data);
                        int start = 0;
                        if (mData != null) {
                            start = mData.size();
                        }
                        View itemView = holder.itemView;
                        MultiItemTypeAdapter<S> adapter;
                        RecyclerView.Adapter innerAdapter = mRecyclerAdapter.getInnerAdapter();
                        if (innerAdapter instanceof MultiItemTypeAdapter) {
                            adapter = (MultiItemTypeAdapter<S>) innerAdapter;
                        } else {
                            HeaderAndFooterWrapper headAdapter = (HeaderAndFooterWrapper) innerAdapter;
                            start += headAdapter.getHeaderCount();
                            adapter = (MultiItemTypeAdapter<S>) headAdapter.getInterAdapter();
                        }
                        if (data != null && data.getList() != null && data.getList().size() != 0) {
                            List<S> itemList = getDataList(data);
                            if (!isUpdateLastOne) {
                                if (mData != null) {
                                    mData.addAll(itemList);
                                }
                            }

                            if (adapter != null) {
                                if (!isUpdateLastOne) {
                                    adapter.addItems(itemList);
                                    mRecyclerAdapter.notifyItemRangeInserted(start, itemList.size());
                                } else {
                                    adapter.changeItem(itemList.get(adapter.getItemCount() - 1),
                                            adapter.getItemCount() - 1);
                                    mRecyclerAdapter.notifyItemChanged(start - 1);
                                    List<S> list = getList(mData, adapter.getItemCount());
                                    adapter.addItems(list);
                                    mRecyclerAdapter.notifyItemRangeInserted(start, list.size());
                                }
                            }
                            Log.d(TAG, "call: Loading");
                            itemView.findViewById(R.id.ItemLoadMore_pb).setVisibility(View.VISIBLE);
                            itemView.findViewById(R.id.ItemLoadMore_tv_load).setVisibility(View.INVISIBLE);
                        } else {
                            Log.d(TAG, "call: Finish");
                            itemView.findViewById(R.id.ItemLoadMore_pb).setVisibility(View.INVISIBLE);
                            itemView.findViewById(R.id.ItemLoadMore_tv_load).setVisibility(View.VISIBLE);
                            mPage--;
                            if (!mRecyclerAdapter.isFinish()) {
                                final int finalStart = start;
                                new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                                    @Override
                                    public void run() {
                                        Log.d(TAG, "run: Finally");
                                        mRecyclerAdapter.setFinish(true);
                                        mRecyclerAdapter.notifyItemRemoved(finalStart);
                                    }
                                }, 1500);
                            }
                        }
                    }
                }, new Action1<Throwable>() {
                    @Override
                    public void call(Throwable throwable) {
                        Log.d(TAG, "call: " + throwable);
                    }
                }, new Action0() {
                    @Override
                    public void call() {
                        Log.d(TAG, "call: Action Finally");
                    }
                });

    }

    private List<S> getList(List<S> list, int start) {
        List<S> result = new ArrayList<>();
        for(int x = start; x < list.size(); x++) {
            result.add(list.get(x));
        }
        return result;
    }

    protected List<S> getDataList(T data) {
        return data.getList();
    }
}
